#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>

struct BoxMullerState
{
        double x1, x2, w, y1, y2;
        int useLast;
        struct drand48_data random;
};

void initBoxMullerState(struct BoxMullerState* state)
{
        state->random.__init = 0;
        state->useLast = 0;
        
        struct timeval now;
	gettimeofday(&now, NULL);
	state->random.__x[0] = now.tv_usec;
}

double boxMullerRandom(struct BoxMullerState* state)
{
        double randomNumber;

        if (state->useLast)
        {
                state->y1 = state->y2;
                state->useLast = 0;
        }
        else
        {
                do
                {
                        drand48_r(&state->random, &state->x1);
                        state->x1 = 2.0 * state->x1 - 1.0;
                        drand48_r(&state->random, &state->x2);
                        state->x2 = 2.0 * state->x2 - 1.0;
                        state->w = state->x1 * state->x1 + state->x2 * state->x2;
                }
                while (state->w >= 1.0);

                state->w = sqrt((-2.0 * log(state->w)) / state->w);
                state->y1 = state->x1 * state->w;
                state->y2 = state->x2 * state->w;
                state->useLast = 1;
        }

        return state->y1;
}


//metodo para calcular o desvio padrao dos dados
float dev(float *v, float mean, long int n)
{
   long int i;
	double sum = 0;
	for(i = 0; i < n-1; i++)
	{
		sum += pow(v[i]-mean, 2);
	}

	return sqrt(sum/n);
}

int main()
{
	//variaveis e struct para gerar os numeros aleatorios
/* OBS: cada thread deve possuir uma variavel do tipo BoxMullerState. */
	struct BoxMullerState state;
	
	/* O init deve ser chamado! */
	initBoxMullerState(&state);
	
   //variaveis de entrada do modelo de black_scholes
	double S, E, r, sigma, T;
	double random, t;	
	long int m;

	//lendo a entrada
   scanf("%f ", &S);
	scanf("%f ", &E);
	scanf("%f ", &r);
	scanf("%f ", &sigma);
	scanf("%f ", &T);
	scanf("%ld ", &m);

	float trials[m], term1, term2;
	float means = 0, e, var;                 
	float confwidth, confmin, confmax;	
	//algoritmo de black_scholes com monte carlo

	long int i;
	for (i = 0; i < m; i++)
	{
		random = boxMullerRandom(&state);
		term1 = (r-0.5*pow(sigma, 2))*T;
		term2 = sigma*sqrt(T)*random;
		e = exp(term1 + term2);
		t = S*e;
		if((t-E) <= 0)
			trials[i] = 0;
		else
			trials[i] = exp((-r)*T)*(t-E);
		//calculando a media para aproveitar o laco
		means += trials[i];
	}

	//calculando o intervalo de confianca
	means = means/m;
	var = dev(trials, means, m);

	confwidth = 1.96*var/sqrt(m);
	confmin = means - confwidth;
	confmax = means + confwidth;

  //printando os resultados 

	printf("S %f\n", S);
	printf("E %f\n", E);
	printf("r %f\n", r);	
	printf("sigma %f\n", sigma);
	printf("T %f\n", T);
	printf("M %ld\n", m);
	printf("Confidence interal: (%f, %f)", confmin, confmax);

	return 0;
}

